package com.jetpackframework.fixpatch;

import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import android.util.Log;

import com.jetpackframework.Application;
import com.jetpackframework.ContextUtil;
import com.jetpackframework.Reflector;
import com.jetpackframework.virtual.VirtualDexClassLoader;

import java.io.File;
import java.io.IOException;

public class FixpatchInstaller {
    public static void install(Application application,Fixpatch fixpatch) {
        //1.创建classloader替换原有的classloader
        ClassLoader classLoader = createClassLoader(fixpatch.getDexPath());
        injectClassLoader(application,classLoader);

        //2.通过bsdiff合并so  并释放到so指定目录。
        File sofile = new File(fixpatch.getSoPath());
        File[] files = sofile.listFiles();
        for (File patchFile : files){
            String soFile = "/data/data/"+ContextUtil.get().getPackageName()+"/lib/"+patchFile.getName();
            try {
                BSPatch.patchFast(new File(soFile),new File(soFile),patchFile,0);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void injectClassLoader(Application application, ClassLoader classLoader) {
        Thread.currentThread().setContextClassLoader(classLoader);

        try {
            Context mBase = Reflector.with(application).field("mBase").get();
            Reflector.with(mBase).field("mClassLoader").set(classLoader);

            Object mPackageInfo = Reflector.with(mBase).field("mPackageInfo").get();
            Reflector.with(mPackageInfo).field("mClassLoader").set(classLoader);

            Object currentActivityThread = Reflector.on("android.app.ActivityThread").method("currentActivityThread").call();
            Object mBoundApplication = Reflector.with(currentActivityThread).field("mBoundApplication").get();
            Object info = Reflector.with(mBoundApplication).field("info").get();
            Reflector.with(info).field("mClassLoader").set(classLoader);

            if (Build.VERSION.SDK_INT < 27) {
                Resources res = application.getResources();
                Reflector.with(res).field("mClassLoader").set(classLoader);
                Reflector.with(Reflector.with(res).field("mDrawableInflater").get()).field("mClassLoader").set(classLoader);
            }
        } catch (Reflector.ReflectedException e) {
            e.printStackTrace();
        }

    }

    private static ClassLoader createClassLoader(String dexPath) {
        return new VirtualDexClassLoader(dexPath, ContextUtil.get().getCacheDir(), "", FixpatchInstaller.class.getClassLoader());
    }
}
